package com.tbit.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * created by Kang on 2019/4/16 8:46
 * description:反射工具类
 */
@Slf4j
public class ReflectUtils {
    public static List<String> typeList = new ArrayList<>();
    //定义基本类型
    private static String[] types = {"java.lang.Integer", "java.lang.Double",
            "java.lang.Float", "java.lang.Long", "java.lang.Short",
            "java.lang.Byte", "java.lang.Boolean", "java.lang.Char",
            "java.lang.String", "int", "double", "long", "short", "byte",
            "boolean", "char", "float", "java.util.Date"};

    static {
        for (String type : types) {
            typeList.add(type);
        }
    }

    /**
     * 获取包装类的属性和属性值
     *
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Object> getNameValues(Object obj) throws IllegalAccessException {
        if (null == obj) {
            return new HashMap<>();
        }
        Class<?> clazz = obj.getClass();
        Map<String, Object> nameValueMap = new HashMap<>();
        if (typeList.contains(clazz.getName())) {//如果是基本类型，则直接抛出异常
            throw new RuntimeException("not support the list class!");
        } else {//只解析包装类
            //获取父类
            for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    //过滤静态属性
                    if (Modifier.isStatic(field.getModifiers())) {
                        continue;
                    }
                    // 处理文件对象
                    if (field.get(obj) instanceof MultipartFile) {
                        MultipartFile multipartFile = (MultipartFile) field.get(obj);
                        nameValueMap.put(field.getName(), multipartFile.getOriginalFilename());
                        continue;
                    }
                    nameValueMap.put(field.getName(), field.get(obj));
                }
            }
        }

        return nameValueMap;
    }

    /**
     * 使用反射机制，将string类型为null转换成需要的值
     */
    public static Object checkNull(Object obj) {
        Class<? extends Object> clazz = obj.getClass();
        // 获取实体类的所有属性，返回Field数组
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            // 可访问私有变量
            field.setAccessible(true);
            // 获取属性类型
            String type = field.getGenericType().toString();
            // 如果type是类类型，则前面包含"class "，后面跟类名
            if ("class java.lang.String".equals(type)) {
                // 将属性的首字母大写
                String methodName = field.getName().replaceFirst(field.getName().substring(0, 1),
                        field.getName().substring(0, 1).toUpperCase());
                try {
                    Method methodGet = clazz.getMethod("get" + methodName);
                    // 调用getter方法获取属性值
                    String str = (String) methodGet.invoke(obj);
                    if (StringUtils.isBlank(str)) {
                        // Method methodSet = clazz.getMethod("set" +
                        // methodName, new Class[] { String.class });
                        // methodSet.invoke(o, new Object[] { "" });
                        // 如果为null的String类型的属性则重新复制为空字符串
//                        field.set(obj, field.getType().getConstructor(field.getType()).newInstance(""));
                        //如果为null的String类型的属性则重新复制为0
                        field.set(obj, field.getType().getConstructor(field.getType()).newInstance("0.00%"));
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return obj;
    }


    @SuppressWarnings("rawtypes")
    public static Object assign(Object soruce, Object target, String[] ignoreFields) {
        try {
            Class clsSource = soruce.getClass();
            Field[] fieldsSource = clsSource.getDeclaredFields();
            Class clsTarget = target.getClass();
            Field[] fieldsTarget = clsTarget.getDeclaredFields();
            List<String> igfields = new ArrayList<String>();
            if (ignoreFields != null && ignoreFields.length > 0) {
                igfields.addAll(Arrays.asList(ignoreFields));
            }
            for (int i = 0; i < fieldsSource.length; i++) {
                Field fS = fieldsSource[i];
                Field fT = fieldsTarget[i];
                fS.setAccessible(true);
                fT.setAccessible(true);
                if (fS.get(soruce) != null && !igfields.contains(fS.getName())) {
                    fT.set(target, fS.get(soruce));
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return target;
    }
}
